package com.github.rnewson.couchdb.lucene;

/**
 * Copyright 2010 Robert Newson
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0 
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.HierarchicalINIConfiguration;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.client.HttpClient;
import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.github.rnewson.couchdb.lucene.couchdb.Couch;
import com.github.rnewson.couchdb.lucene.couchdb.Database;
import com.github.rnewson.couchdb.lucene.couchdb.DesignDocument;
import com.github.rnewson.couchdb.lucene.couchdb.View;
import com.github.rnewson.couchdb.lucene.util.ServletUtils;

public final class GenerateWebServlet extends HttpServlet {

	private static final Logger LOG = Logger
			.getLogger(GenerateWebServlet.class);

	private static final long serialVersionUID = 1L;

	private final HttpClient client;

	private final Map<Database, GenerateWebs> webSites = new HashMap<Database, GenerateWebs>();

	private final HierarchicalINIConfiguration ini;

	private final File root;

	private final Map<Database, Thread> threads = new HashMap<Database, Thread>();

	public GenerateWebServlet(final HttpClient client, final File root,
			final HierarchicalINIConfiguration ini) {
		this.client = client;
		this.root = root;
		this.ini = ini;
	}

	public Map<Database, GenerateWebs> getWebSites() {
		return webSites;
	}

	public Map<Database, Thread> getThreads() {
		return threads;
	}

	// private void cleanup(final HttpServletRequest req,
	// final HttpServletResponse resp) throws IOException, JSONException {
	// final Couch couch = getCouch(req);
	// final Set<String> dbKeep = new HashSet<String>();
	// final JSONArray databases = couch.getAllDatabases();
	// for (int i=0; i< databases.length(); i++) {
	// final Database db = couch.getDatabase(databases.getString(i));
	// final UUID uuid = db.getUuid();
	// if (uuid == null) {
	// continue;
	// }
	// dbKeep.add(uuid.toString());
	//
	// final Set<String> viewKeep = new HashSet<String>();
	//
	// for (final DesignDocument ddoc : db.getAllDesignDocuments()) {
	// for (final View view : ddoc.getAllViews().values()) {
	// viewKeep.add(view.getDigest());
	// }
	// }
	//
	// // Delete all indexes except the keepers.
	// final File[] dirs = DatabaseIndexer.uuidDir(root,
	// db.getUuid()).listFiles();
	// if (dirs == null) {
	// LOG.warn(DatabaseIndexer.uuidDir(root, db.getUuid())
	// + " is not a directory or could not be read.");
	// ServletUtils.sendJsonError(req, resp, 500, "index_dir_perms");
	// return;
	// } else {
	// for (final File dir : dirs) {
	// if (!viewKeep.contains(dir.getName())) {
	// LOG.info("Cleaning old index at " + dir);
	// FileUtils.deleteDirectory(dir);
	// }
	// }
	// }
	// }
	//
	// // Delete all directories except the keepers.
	// for (final File dir : root.listFiles()) {
	// if (!dbKeep.contains(dir.getName())) {
	// LOG.info("Cleaning old index at " + dir);
	// FileUtils.deleteDirectory(dir);
	// }
	// }
	//
	// resp.setStatus(202);
	// ServletUtils.sendJsonSuccess(req, resp);
	// }
	Map<String, String> m = new HashMap<String, String>();

	private Couch getCouch(final HttpServletRequest req) throws IOException {
		final Configuration section = ini.getSection(new PathParts(req)
				.getKey());
		final String url = section.containsKey("url") ? section
				.getString("url") : null;
		return new Couch(client, url);
	}

	public synchronized GenerateWebs getWebsite(final Database database)
			throws IOException, JSONException {
		GenerateWebs result = webSites.get(database);
		Thread thread = threads.get(database);

		if (result == null || thread == null || !thread.isAlive()) {
			result = new GenerateWebs(client, root, database, ini);
			thread = new Thread(result);
			thread.start();
			// result.awaitInitialization();
			if (result.isClosed()) {
				return null;
			} else {
				webSites.put(database, result);
				threads.put(database, thread);
			}
		}

		return result;
	}

	private GenerateWebs getWebsite(final HttpServletRequest req)
			throws IOException, JSONException {
		final Couch couch = getCouch(req);
		final Database database = couch.getDatabase(new PathParts(req)
				.getDatabaseName());
		return getWebsite(database);
	}

	private void handleWelcomeReq(final HttpServletRequest req,
			final HttpServletResponse resp) throws ServletException,
			IOException, JSONException {
		final Package p = this.getClass().getPackage();
		final JSONObject welcome = new JSONObject();
		welcome.put("couchdb-lucene", "Welcome");
		welcome.put("version", p.getImplementationVersion());
		ServletUtils.sendJson(req, resp, welcome);
	}

	@Override
	protected void doGet(final HttpServletRequest req,
			final HttpServletResponse resp) throws ServletException,
			IOException {
		try {
			doGetInternal(req, resp);
		} catch (final JSONException e) {
			resp.sendError(500);
		}
	}

	private void handlerizhiReq(final HttpServletRequest req,
			final HttpServletResponse resp, String fileName)
			throws ServletException, IOException, JSONException {
		final Package p = this.getClass().getPackage();
		final JSONObject welcome = new JSONObject();
		synchronized (Main.class) {
			long at = 0l;
		}
		String path = "F:\\couchdb" + fileName;
		File f = new File(path);
		if (f.exists()) {
			BufferedReader input = new BufferedReader(new FileReader(f));

			String line = input.readLine();
			String content = "";
			while (line != null) {
				content += line + ",";

				line = input.readLine();
			}
			// System.out.println(s1);
			content = content.substring(0, content.length() - 1);
			input.close();
			welcome.put(fileName, content);
		} else {
			welcome.put(fileName, "对不起，该日志文件不存在！！");
		}
		welcome.put("version", p.getImplementationVersion());
		ServletUtils.sendJson(req, resp, welcome);
	}

	private void handlerizhiReq(final HttpServletRequest req,
			final HttpServletResponse resp, String fileName1, String fileName2)
			throws ServletException, IOException, JSONException {
		final Package p = this.getClass().getPackage();
		final JSONObject welcome = new JSONObject();
		int start = Integer.parseInt(fileName1);
		int end = Integer.parseInt(fileName2);
		for (int i = start; i <= end; i++) {
			String fileName = Integer.toString(i);
			String path = "F:\\couchdb\\log\\" + fileName;
			File f = new File(path);

			if (f.exists()) {
				BufferedReader input = new BufferedReader(new FileReader(f));

				String line = input.readLine();
				String content = "";
				while (line != null) {
					content += line + ",";

					line = input.readLine();
				}
				// System.out.println(s1);
				content = content.substring(0, content.length() - 1);
				input.close();
				welcome.put(fileName, content);
				// welcome.put("version", p.getImplementationVersion());
				// ServletUtils.sendJson(req, resp, welcome);
			} else {
				welcome.put(fileName, "对不起，该日志文件不存在！！");
				continue;
			}

		}

		welcome.put("version", p.getImplementationVersion());
		ServletUtils.sendJson(req, resp, welcome);
	}

	private void doGetInternal(final HttpServletRequest req,
			final HttpServletResponse resp) throws ServletException,
			IOException, JSONException {

		int numParameter = 0;
		// new HttpServletRequest().getParameterNames();
		Enumeration c = req.getParameterNames();

		while (c.hasMoreElements()) {
			numParameter++;
			c.nextElement();
		}

		switch (numParameter) {
		case 0:
			handleWelcomeReq(req, resp);
			return;
		case 1:

			if (req.getParameter("q1") == "") {
				ServletUtils.sendJsonError(req, resp, 400, "bad_request");
			} else {
				// System.out.println(req.getParameter("q"));
				String fileName = req.getParameter("q1");
				String tempLog = null;
				int last = fileName.lastIndexOf("_");
				if (last != -1) {
					tempLog = fileName.substring(last, fileName.length());
					if (tempLog.compareTo("_log") == 0) {
						fileName = "\\log\\" + fileName;
					} else {
						fileName = "\\webs\\" + fileName;
					}
				} else {
					fileName = "\\webs\\" + fileName;
				}
				handlerizhiReq(req, resp, fileName);
			}
			return;
		case 2:
			if (req.getParameter("q1") == "" || req.getParameter("q2") == "") {
				ServletUtils.sendJsonError(req, resp, 400, "bad_request");
			} else {
				// System.out.println(req.getParameter("q"));
				String fileName1 = req.getParameter("q1");
				String fileName2 = req.getParameter("q2");
				handlerizhiReq(req, resp, fileName1, fileName2);
			}
			return;
		case 5:
			final GenerateWebs webSite = getWebsite(req);
			if (webSite == null) {
				ServletUtils.sendJsonError(req, resp, 500,
						"error_creating_index");
				return;
			}
			if (req.getParameter("q") == null) {
				// indexer.info(req, resp);
			} else {
				// indexer.search(req, resp);
			}
			return;
		case 3:
			final GenerateWebs webSite1 = getWebsite(req);
			if (webSite1 == null) {
				ServletUtils.sendJsonError(req, resp, 500,
						"error_creating_index");
				return;
			}
		}

		ServletUtils.sendJsonError(req, resp, 400, "bad_request");
	}

	// @Override
	// protected void doPost(final HttpServletRequest req,
	// final HttpServletResponse resp) throws ServletException,
	// IOException {
	// try {
	// doPostInternal(req, resp);
	// } catch (final JSONException e) {
	// resp.sendError(500);
	// }
	// }
	//
	// private void doPostInternal(final HttpServletRequest req, final
	// HttpServletResponse resp)
	// throws IOException, JSONException {
	// switch (StringUtils.countMatches(req.getRequestURI(), "/")) {
	// case 3:
	// if (req.getPathInfo().endsWith("/_cleanup")) {
	// // cleanup(req, resp);
	// return;
	// }
	// break;
	// case 6:
	// final GenerateWebs indexer = getIndexer(req);
	// // indexer.admin(req, resp);
	// return;
	// }
	// ServletUtils.sendJsonError(req, resp, 400, "bad_request");
	// }

}
